home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Magazine / Online / OpenURL / Developer / Source / OpenURL.c < prev    next >
C/C++ Source or Header  |  1999-09-26  |  7KB  |  261 lines

  1. /* 
  2.  * OpenURL -- A Workbech/CLI frontend for "openurl.library".
  3.  *
  4.  * Written by Thomas Aglassinger <agi@sbox.tu-graz.ac.at>
  5.  * Placed in the public domain.
  6.  *
  7.  * Based on material provided by Troels Walsted Hansen <troels@thule.no>
  8.  */
  9.  
  10. #include <exec/memory.h>
  11. #include <dos/dos.h>
  12. #include <libraries/openurl.h>
  13. #include <intuition/intuition.h>
  14.  
  15. #include <string.h>
  16.  
  17. #include "SmartReadArgs.h"
  18.  
  19. #include <proto/exec.h>
  20. #include <proto/dos.h>
  21. #include <proto/intuition.h>
  22. #include <proto/openurl.h>
  23.  
  24. static const char *version = "\0$VER: OpenURL 1.1 " __AMIGADATE__;
  25.  
  26. #define TEMPLATE "URL/A,NOSHOW/S,NOFRONT/S,NEWWIN/S,NOLAUNCH/S,FILE/S"
  27. enum
  28. {
  29.    A_URL, A_NOSHOW, A_NOFRONT, A_NEWWIN, A_NOLAUNCH, A_FILE, A_MAX
  30. };
  31.  
  32. /* Maximum length an URL can get according to w3c. Currently, CLI
  33.  * imposes even a smaller limit of 512. */
  34. #define MAXIMUM_URL_LENGTH 1024
  35.  
  36. struct Library *OpenURLBase;
  37.  
  38. #define OPENURL_VERSION      1  /* Minimum version of openurl.library */
  39. #define OPENURL_VERSION_STR "1" /* Used by error message */
  40.  
  41. #define MAXIMUM_ERROR_LENGTH 120    /* Size of buffer for error messages */
  42.  
  43. /* Some shit necessary because C standard libraries suck */
  44. ULONG ulong_max(ULONG a, ULONG b)
  45. {
  46.    if (a > b)
  47.    {
  48.       return a;
  49.    }
  50.    else
  51.    {
  52.       return b;
  53.    }
  54. }
  55.  
  56. /* Main function
  57.  *
  58.  * Note that the startup code of SAS/c sets argc=0 when started from
  59.  * workbench. This fact is used to auto-enable FILE in such a case.
  60.  */
  61. int main(int argc, char *argv[])
  62. {
  63.    int return_code = RETURN_FAIL;
  64.  
  65.    /* Error code from dos.library's IoErr() */
  66.    LONG error_code = 0;
  67.    /* Description of the action failed. If error_code is 0, only this
  68.     * text is displayed. Otherwise, also the DOS error message is
  69.     * appended. */
  70.    STRPTR error_cause = NULL;
  71.  
  72.    /* Workbench startup message or NULL if started from CLI */
  73.    struct WBStartup *wb_startup = NULL;
  74.  
  75.    /* Buffer for error messages. This is not allocated dynamically because
  76.     * then it might not exist in case of no memory. */
  77.    UBYTE error_buffer[MAXIMUM_ERROR_LENGTH] =
  78.    {NULL};
  79.  
  80.    if ((OpenURLBase = OpenLibrary("openurl.library", OPENURL_VERSION)))
  81.    {
  82.       struct SmartArgs smart_args =
  83.       {NULL};
  84.       LONG args[A_MAX] =
  85.       {0};
  86.  
  87.       /* The URL passed to URL_Open() */
  88.       STRPTR real_url = NULL;
  89.  
  90.       /* The fully qualified filename, if any */
  91.       STRPTR filename = NULL;
  92.  
  93.       /* Prepare argument parsing */
  94.       smart_args.sa_Template = TEMPLATE;
  95.       smart_args.sa_Parameter = args;
  96.       smart_args.sa_FileParameter = A_URL;
  97.       smart_args.sa_Window = "CON:////OpenURL/AUTO/CLOSE/WAIT";
  98.  
  99.       return_code = RETURN_ERROR;
  100.  
  101.       /* Auto-enable FILE switch when started from WB */
  102.       if (argc == 0)
  103.       {
  104.          wb_startup = (struct WBStartup *) argv;
  105.          args[A_FILE] = 1;
  106.       }
  107.  
  108.       /* Parse arguments, either from Workbench or CLI */
  109.       error_code = SmartReadArgs(wb_startup, &smart_args);
  110.  
  111.       /* Allocate string buffers. This reduces stack usage and also
  112.        * makes the string buffers being checked by Mungwall.
  113.        *
  114.        * Yes, this wastes some memory if FILE is not set, but makes the
  115.        * error handling easier.
  116.        *
  117.        * Yes, we could use a 2K buffer with filename = real_url + 1024 to
  118.        * use only one allocation. This however would reduce the possibilty
  119.        * for out-of-bounds checks for the end of one/beginning of the
  120.        * other string. */
  121.       if (error_code == 0)
  122.       {
  123.          /* Allocate string buffers */
  124.          real_url = AllocVec(MAXIMUM_URL_LENGTH, MEMF_ANY);
  125.          filename = AllocVec(MAXIMUM_URL_LENGTH, MEMF_ANY);
  126.          if ((real_url == NULL) || (filename == NULL))
  127.          {
  128.             /* Not enough memory */
  129.             SetIoErr(ERROR_NO_FREE_STORE);
  130.             error_code = IoErr();
  131.          }
  132.       }
  133.  
  134.       if (error_code == 0)
  135.       {
  136.          if (args[A_FILE])
  137.          {
  138.             /* Expand the filename to a fully qualified URL */
  139.             BPTR lock = Lock((STRPTR) args[A_URL], ACCESS_READ);
  140.  
  141.             if (lock != NULL)
  142.             {
  143.                if (NameFromLock(lock, filename, MAXIMUM_URL_LENGTH))
  144.                {
  145.                   strcpy(real_url, "file://localhost/");
  146.                   strncat(real_url, filename, MAXIMUM_URL_LENGTH);
  147.                }
  148.                else
  149.                {
  150.                   error_cause = "Error obtaining full filename";
  151.                   error_code = IoErr();
  152.                }
  153.                UnLock(lock);
  154.             }
  155.             else
  156.             {
  157.                error_cause = "Error opening input file";
  158.                error_code = IoErr();
  159.             }
  160.          }
  161.          else
  162.          {
  163.             /* Simply use the URL passed in arguments, assuming it is
  164.              * an already fully qualified URL of any protocol. Possible
  165.              * errors are now treated by the browser. */
  166.             strncpy(real_url, (STRPTR) args[A_URL], MAXIMUM_URL_LENGTH);
  167.          }
  168.  
  169.          /* Make sure that the URL gets a trailing zero (just in case
  170.           * someone passed a too long one). */
  171.          real_url[MAXIMUM_URL_LENGTH - 1] = '\0';
  172.  
  173.          if (error_code == 0)
  174.          {
  175.             /* Really show it */
  176.             if (URL_Open(real_url,
  177.                          URL_Launch, !args[A_NOLAUNCH],
  178.                          URL_Show, !args[A_NOSHOW],
  179.                          URL_BringToFront, !args[A_NOFRONT],
  180.                          URL_NewWindow, args[A_NEWWIN],
  181.                          TAG_DONE))
  182.             {
  183.                return_code = RETURN_OK;
  184.             }
  185.             else
  186.             {
  187.                error_code = 0;
  188.                if (args[A_NOLAUNCH])
  189.                {
  190.                   error_cause = "Could not find browser port";
  191.                }
  192.                else
  193.                {
  194.                   error_cause = "Could not launch browser";
  195.                }
  196.             }
  197.          }
  198.       }
  199.       else
  200.       {
  201.          error_cause = "Error in arguments";
  202.       }
  203.  
  204.       /* Free extended read args (even in case of error) */
  205.       SmartFreeArgs(&smart_args);
  206.  
  207.       /* Release all other resources */
  208.       if (filename != NULL)
  209.       {
  210.          FreeVec(filename);
  211.       }
  212.       if (real_url != NULL)
  213.       {
  214.          FreeVec(real_url);
  215.       }
  216.  
  217.       CloseLibrary(OpenURLBase);
  218.    }
  219.    else
  220.    {
  221.       error_cause =
  222.          "Could not find \"openurl.library\", "
  223.          "version " OPENURL_VERSION_STR;
  224.    }
  225.  
  226.    /* Create error message in error_buffer (if any) */
  227.    if (error_code != 0)
  228.    {
  229.       Fault(error_code, error_cause, error_buffer, MAXIMUM_ERROR_LENGTH);
  230.    }
  231.    else if (error_cause != NULL)
  232.    {
  233.       strncpy(error_buffer, error_cause, MAXIMUM_ERROR_LENGTH - 1);
  234.    }
  235.  
  236.    /* Display error message in CLI or Requester (if any) */
  237.    if (error_buffer[0] != '\0')
  238.    {
  239.       if (wb_startup != NULL)
  240.       {
  241.          struct EasyStruct error_requester =
  242.          {
  243.             sizeof(struct EasyStruct),
  244.             0,
  245.             "OpenURL Error",
  246.             "%s",
  247.             "Cancel"
  248.          };
  249.  
  250.          EasyRequest(NULL, &error_requester, NULL, error_buffer);
  251.       }
  252.       else
  253.       {
  254.          FPuts(Output(), error_buffer);
  255.          FPuts(Output(), "\n");
  256.       }
  257.    }
  258.  
  259.    return (return_code);
  260. }
  261.